package com.seed.application.gateway.impl;

import cn.hutool.core.util.StrUtil;
import com.seed.application.Sa;
import com.seed.application.env.MicroEnv;
import com.seed.application.env.ActionEnv;
import com.seed.application.gateway.SeedGateway;
import com.seed.application.service.SeedService1;
import com.seed.application.service.pojo.SeedAction;
import com.seed.core.RequestWrapper;
import com.seed.core.ResponseWrapper;
import com.seed.core.action.Action;
import com.seed.core.pojo.R;
import com.seed.core.pojo.seed.Seed;
import com.seed.core.query.App;
import com.seed.manager.LibManager;
import com.seed.uaa.Uaa;
import com.seed.util.StrKit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 1. 白名单地址
 * 2. 配置地址(所有服务都有，不能被覆盖，适用于一切http请求方法)
 * 3. 保留地址(所有服务都有，不能被覆盖)
 * 4. uaa地址(主应用服务才有，不能被覆盖)
 * 5. 库地址(引用了库的服务就有，不能被覆盖)
 * 6. 幽灵地址(最后的保障)
 */
@Slf4j
public class SingleSeedGateway implements SeedGateway {

    protected RequestWrapper request;
    protected ResponseWrapper response;

    /**
     * 单体应用：地址以应用名称或微服务名称开头，该类型的应用不能有属于自己的controller，如果需要自定义，则需要先定义成库，再引用
     * 请应用请求形如：/~/action, /~/seed/action, /~/seed/action/pathVariable
     * 微服务请求形如：/micro/action, /micro/seed/action, /micro/seed/action/pathVariable
     */
    @Override
    public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        this.request = new RequestWrapper(req);
        this.response = new ResponseWrapper(res);

        set(req.getRequestURI());
        ActionEnv.setMethod(RequestMethod.valueOf(req.getMethod()));

        String microName = MicroEnv.getMicroName();
        String seedName = ActionEnv.getSeedName();
        String actionName = ActionEnv.getActionName();
        RequestMethod method = ActionEnv.getMethod();
        if(StrUtil.isBlank(actionName)) { // 2. 配置地址(所有服务都有)
            response.sendJSON(R.data(Sa.getConfiguration().toFront()));
            return;
        }

        if(StrUtil.isBlank(seedName)) { // 保留地地址不在任何模块
            Action action = Sa.getAction(method, actionName);
            if(action != null) { // 3. 保留地址(所有服务都有)
                forwardTo(action);
                return;
            }
        }

        if(StrUtil.isBlank(microName)) {
            Sa.switchDataSourceKey();
            Action action = Uaa.getAction(seedName, method, actionName);
            if(action == null) {
                doMicroFilter();
            } else { // 4. uaa地址(主应用服务才有)
                forwardTo(action);
            }
        } else {
            App app = Sa.getApp();
            if(app.existMicro(microName)) {
                Sa.switchDataSourceKey();
                doMicroFilter();
            } else {
                response.send404();
            }
        }
    }

    private void doMicroFilter() throws IOException, ServletException {
        RequestMethod method = ActionEnv.getMethod();
        String microName = MicroEnv.getMicroName();
        String seedName = ActionEnv.getSeedName();
        String actionName = ActionEnv.getActionName();

        App app = Sa.getApp();
        List<String> libs = app.getConfigurationLibs(microName);
        if(libs != null && !libs.isEmpty()) {
            Action action = LibManager.getAction(seedName, method, actionName, libs);
            if(action != null) { // 5. 库地址(引用了库的服务就有)
                forwardTo(action);
                return;
            }
        }

        SeedAction seedAction = null; // getSeedAction();
        Seed seed = seedAction.getSeed();
        Action action = seedAction.getAction();
        new SeedService1(seed, action, request, response).exec(); // 6. 幽灵地址(最后的保障)
    }

    /**
     * 检查登录，检查权限，重定向
     * @param action 当前访问action对象
     */
    protected void forwardTo(Action action) {
        Boolean checkLogin = action.getCheckLogin();
        if(checkLogin == null || checkLogin) checkLogin();

        Boolean checkAction = action.getCheckAction();
        if(checkAction == null || checkAction) checkPermisstion();

        String seedName = ActionEnv.getSeedName();
        String actionName = ActionEnv.getActionName();
        String pathVariable = ActionEnv.getPathVariable();

//        request.setAttribute("seedName", StrUtil.isBlank(seedName) ? action.getSeedName() : seedName);
//        request.setAttribute("actionName", actionName);

        StringBuilder sb = new StringBuilder();
        if(StrUtil.isNotBlank(seedName)) sb.append('/').append(seedName);
        sb.append('/').append(actionName);
        if(StrUtil.isNotBlank(pathVariable)) sb.append('/').append(pathVariable);

        String path = sb.toString();
        System.out.println("path===============");
        System.out.println(path);
//        request.getRequestDispatcher(path).forward(request, response);
        request.forward(path, response.getResponse());
    }

    /**
     * 解析uri
     * @param uri 形如 /micro, /micro/action, /micro/seed/action, /micro/seed/action/pathVariable
     */
    private void set(String uri) {
        if(uri.startsWith("/")) uri = uri.substring(1);

        String[] items = StrKit.cutInTwo(uri, '/', false);
        String microName = items[0];
        uri = items[1];

        if(!"~".equals(microName)) MicroEnv.setMicroName(microName);
        ActionEnv.set(uri);
    }

    private void checkLogin() {
        // TODO
    }

    private void checkPermisstion() {
        // TODO
    }
}
